package cnpm.controller;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;

import cnpm.dto.AddEmployeeDTO;
import cnpm.dto.UserDTO;
import cnpm.entity.Bank;
import cnpm.entity.BrandBank;
import cnpm.entity.Contract;
import cnpm.entity.Department;
import cnpm.entity.Employee;
import cnpm.entity.Insurance;
import cnpm.entity.Literacy;
import cnpm.entity.Nationality;
import cnpm.entity.Office;
import cnpm.service.BankService;
import cnpm.service.BrandBankService;
import cnpm.service.ContractService;
import cnpm.service.DepartmentService;
import cnpm.service.EmployeeService;
import cnpm.service.InsuranceService;
import cnpm.service.LiteracyService;
import cnpm.service.NationalityService;
import cnpm.service.OfficeService;
import cnpm.util.HelperCreateEmployeeID;

/**
 * Servlet implementation class AddEmployeeController
 */
@WebServlet("/AddEmployeeController.do")
public class AddEmployeeController extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private static final int THRESHOLD_SIZE 	= 1024 * 1024 * 3; 	// 3MB
	private static final int MAX_FILE_SIZE 		= 1024 * 1024 * 40; // 40MB
	private static final int MAX_REQUEST_SIZE 	= 1024 * 1024 * 50; // 50MB
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public AddEmployeeController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		
		String employeeID = HelperCreateEmployeeID.createEmployeeID();
		request.setAttribute("employeeID", employeeID);
		RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/_view/_add.jsp");
		dispatcher.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		String action = request.getParameter("action");
		if(action.equals("getAdd")){
			getDataForAdd(request, response);
		}else if(action.equals("getBrandBank")){
			getBrandBank(request, response);
		}else if(action.equals("save")){
			saveEmployee(request, response);
		}else if(action.equals("saveContract")){
			saveContract(request, response);
		}else if(action.equals("saveInsurance")){
			saveInsurance(request, response);
		}
	}
	
	private void getDataForAdd(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String jsonBank = getAllBank();
		String jsonOffice = getAllOffice();
		String jsonNationality = getAllNationality();
		String jsonLiteracy = getAllLiteracy();
		String jsonDepartment = getAllDepartment();
		response.getWriter().write(jsonBank+"~"+jsonOffice+"~"+jsonNationality+"~"+jsonLiteracy+"~"+jsonDepartment);
	}
	
	private void getBrandBank(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		BankService bankS = (BankService) context.getBean("bankService");
		BrandBankService brandS = (BrandBankService) context.getBean("brandBankService");
		response.getWriter().write(String.valueOf(convertListBrandBankToJson(brandS
				.getAllBrandBank(bankS.getBankByID(Integer.parseInt(request.getParameter("bankID")))))));
	}
	
	@SuppressWarnings("rawtypes")
	private void saveEmployee(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		
		String fileName = "";
		boolean femail = true;
		boolean fphone = true;
		boolean fidCard = true;
		boolean faccount = true;
		Map<String,String> model = new LinkedHashMap<String, String>();
		// checks if the request actually contains upload file
		if (!ServletFileUpload.isMultipartContent(request)) {
			PrintWriter writer = response.getWriter();
			writer.println("Request does not contain upload data");
			writer.flush();
			return;
		}
		// configures upload settings
		DiskFileItemFactory factory = new DiskFileItemFactory();
		factory.setSizeThreshold(THRESHOLD_SIZE);
		factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
		
		ServletFileUpload upload = new ServletFileUpload(factory);
		upload.setFileSizeMax(MAX_FILE_SIZE);
		upload.setSizeMax(MAX_REQUEST_SIZE);
		
		// constructs the directory path to store upload file
		String uploadPath = getServletContext().getRealPath("/upload");
		// creates the directory if it does not exist
		File uploadDir = new File(uploadPath);
		if (!uploadDir.exists()) {
			uploadDir.mkdir();
		}
		
		try {
			// parses the request's content to extract file data
			List formItems = upload.parseRequest(request);
			Iterator iter = formItems.iterator();
			// iterates over form's fields
			while (iter.hasNext()) {
				FileItem item = (FileItem) iter.next();
				if(item.isFormField()){			
					String name = item.getFieldName();
				    String value = item.getString();
				    model.put(name, value);
				}
				// processes only fields that are not form fields
				else{
					String  filePathStored = getServletContext().getInitParameter("imagePath");
					fileName = new File(item.getName()).getName();
					if(!fileName.equals("")){
						String filePath = filePathStored + File.separator + fileName;					
						File storeFile = new File(filePath);
						item.write(storeFile);
					}
				}
			}
		} catch (Exception ex) {
			ex.getMessage();
		}
		
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		NationalityService nationalityS = (NationalityService) context.getBean("nationalityService");
		LiteracyService literacyS = (LiteracyService) context.getBean("literacyService");
		DepartmentService deptS = (DepartmentService) context.getBean("departmentService");
		BankService bankS = (BankService) context.getBean("bankService");
		BrandBankService brandS = (BrandBankService) context.getBean("brandBankService");
		OfficeService officeS = (OfficeService) context.getBean("officeService");
		EmployeeService empS = (EmployeeService) context.getBean("employeeService");
		
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Calendar cal = Calendar.getInstance();
		
		UserDTO user = (UserDTO)request.getSession().getAttribute("User");
		
		if(empS.isExitEmail(model.get("empEmail"))){
			femail= false;
		}
		
		if(empS.isExitIndentityCard(model.get("empIDCard"))){
			fidCard= false;
		}
		
		if(empS.isExitPhone(model.get("empPhone"))){
			fphone= false;
		}
		
		if(empS.isExitAccountBank(model.get("empAccountBank"), bankS.getBankByID(Integer.parseInt(model.get("empBank"))))){
			faccount= false;
		}
		
		Employee emp = new Employee();
		if(!fileName.equals("")){
			emp.setImage("image/upload/"+fileName);
		}
		emp.setEmployeeID(model.get("empID"));
		emp.setFirstName(model.get("empFirstName"));
		emp.setBirthdate(model.get("empBirthDate"));
		emp.setNationality(nationalityS.getNationalityByID(Integer.parseInt(model.get("empNationality"))));
		emp.setNaviteLand(model.get("empNativeLand"));
		emp.setEmail(model.get("empEmail"));
		emp.setIndentityCard(model.get("empIDCard"));
		emp.setLiteracy(literacyS.getLiteracyByID(Integer.parseInt(model.get("empLiteracy"))));
		emp.setDepartment(deptS.getDepartmentByID(Integer.parseInt(model.get("empDepartment"))));
		emp.setTitle(model.get("empTitle"));
		emp.setLastName(model.get("empLastName"));
		emp.setGender(Boolean.parseBoolean(model.get("empGender")));
		emp.setMaritalStatus(Boolean.parseBoolean(model.get("empMarital")));
		emp.setCurrentAddress(model.get("empCurrentAddress"));
		emp.setPhone(model.get("empPhone"));
		emp.setBank(bankS.getBankByID(Integer.parseInt(model.get("empBank"))));
		emp.setBrandBank(brandS.getBrandBak(Integer.parseInt(model.get("empBrandBank"))));
		emp.setAccountBank(model.get("empAccountBank"));
		emp.setOffice(officeS.getOffice(Integer.parseInt(model.get("empOffice"))));
		emp.setUserCreate(user.getUsername());
		emp.setCreateDate(dateFormat.format(cal.getTime()));
		
		if(femail && fphone && fidCard && faccount){
			if(empS.saveOrUpdateEmployee(emp) ){
				request.setAttribute("Employee", emp);
				RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/_view/_add_success.jsp");
				dispatcher.forward(request, response);
			}else{
				RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/_view/_add_error.jsp");
				dispatcher.forward(request, response);
			}
		}else{
			AddEmployeeDTO add = new AddEmployeeDTO();
			if(emp.getNationality() == null){
				add.setNationality(0);
			}else{
				add.setNationality(emp.getNationality().getNationalityID());
			}
			
			if(emp.getLiteracy() == null){
				add.setLiteracy(0);
			}else{
				add.setLiteracy(emp.getLiteracy().getLiteracyID());
			}
			
			if(!femail){
				add.setErrorEmail(true);
			}else{
				add.setErrorEmail(false);
			}
			
			if(!fphone){
				add.setErrorPhone(true);
			}else{
				add.setErrorPhone(false);
			}
			
			if(!fidCard){
				add.setErrorIDCard(true);
			}else{
				add.setErrorIDCard(false);
			}
			
			if(!faccount){
				add.setErrorAccountBank(true);
			}else{
				add.setErrorAccountBank(false);
			}
			add.setEmployee(emp);
			request.setAttribute("AddEmployes", add);
			RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/_view/_add_error_info.jsp");
			dispatcher.forward(request, response);
		}
	}
	
	private void saveContract(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		ContractService contractS = (ContractService) context.getBean("contractService");
		EmployeeService empS = (EmployeeService) context.getBean("employeeService");
		
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Calendar cal = Calendar.getInstance();
		
		UserDTO user = (UserDTO)request.getSession().getAttribute("User");
		
		Contract contract = new Contract();
		contract.setContractID(request.getParameter("contractID"));
		contract.setContractType(request.getParameter("contractType"));
		contract.setContractName(request.getParameter("contractName"));
		contract.setRegDate(request.getParameter("regDate"));
		contract.setEndDate(request.getParameter("endDate"));
		contract.setStartDate(request.getParameter("startDate"));
		contract.setSalary(Integer.parseInt(request.getParameter("salary")));
		contract.setUserCreate(user.getUsername());
		contract.setCreateDate(dateFormat.format(cal.getTime()));
		contract.setEmpContract(empS.getEmployeeByID(request.getParameter("employeeID")));
		if(contractS.getContractByID(contract.getContractID()) == null)
			if(contractS.saveOrUpdateContract(contract)){
				response.getWriter().write("Add contract successfull");
			}else{
				response.getWriter().write("Add contract not success");
			}
		else{
			response.getWriter().write("ContractID is exited");
		}
	}
	
	private void saveInsurance(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		InsuranceService insuranceS = (InsuranceService) context.getBean("insuranceService");
		EmployeeService empS = (EmployeeService) context.getBean("employeeService");
		
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Calendar cal = Calendar.getInstance();
		
		UserDTO user = (UserDTO)request.getSession().getAttribute("User");
		
		Insurance insurance = new Insurance();
		insurance.setInsuranceID(request.getParameter("insuracneID"));
		insurance.setInsurancType(request.getParameter("insuranceType"));
		insurance.setRegDate(request.getParameter("insuranceRegDate"));
		insurance.setRegLocation(request.getParameter("insuranceRegPlace"));
		insurance.setPayForm(request.getParameter("payForm")=="0"?"":request.getParameter("payForm"));
		insurance.setMoney(Integer.parseInt(request.getParameter("money")==""?"0":request.getParameter("money")));
		insurance.setUserCreate(user.getUsername());
		insurance.setCreateDate(dateFormat.format(cal.getTime()));
		insurance.setEmpInsurance(empS.getEmployeeByID(request.getParameter("employeeID")));
		if(insuranceS.getInsuranceByID(insurance.getInsuranceID()) == null)
			if(insuranceS.saveOrUpdateInsurance(insurance)){
				response.getWriter().write("Add insurance successfull");
			}else{
				response.getWriter().write("Add insurance not success");
			}
		else{
			response.getWriter().write("InsuranceID is exited");
		}
	}
	
	private String getAllBank(){
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		BankService bankS = (BankService) context.getBean("bankService");
		return convertListBankToJson(bankS.getALlBank());		
	}
	
	private String getAllOffice(){
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		OfficeService officeS = (OfficeService) context.getBean("officeService");
		return convertListOfficeToJson(officeS.getAllOffice());		
	}
	
	private String getAllNationality(){
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		NationalityService nationalityS = (NationalityService) context.getBean("nationalityService");
		return convertListNationalityToJson(nationalityS.getAllNationality());		
	}
	
	private String getAllLiteracy(){
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		LiteracyService literacyS = (LiteracyService) context.getBean("literacyService");
		return convertListLiteracyToJson(literacyS.getAllLiteracy());		
	}
	
	private String getAllDepartment(){
		ApplicationContext context = WebApplicationContextUtils
	            .getRequiredWebApplicationContext((getServletContext()));
		DepartmentService deptS = (DepartmentService) context.getBean("departmentService");
		return convertListDepartmentToJson(deptS.getAllDepartments());
	}
	
	private String convertListBankToJson(List<Bank> banks){
		JsonObject jsonObj;
		JsonArray jsonArray = new JsonArray();
		JsonObject jsonResponse = new JsonObject();
		for(Bank bank: banks){
			jsonObj = new JsonObject();
			jsonObj.addProperty("BankID", bank.getBankID());
			jsonObj.addProperty("BankName", bank.getBankName());
			jsonArray.add(jsonObj);
		}
		jsonResponse.add("BankList", jsonArray);
		return String.valueOf(jsonResponse);
	}
	
	private String convertListOfficeToJson(List<Office> offices){
		JsonObject jsonResponse = new JsonObject();
		JsonArray jsonArray = new JsonArray();
		JsonObject jsonObj;
		for(Office office: offices){
			jsonObj = new JsonObject();
			jsonObj.addProperty("OfficeID", office.getOfficeID());
			jsonObj.addProperty("OfficeName", office.getOfficeName());
			jsonArray.add(jsonObj);
		}
		jsonResponse.add("OfficeList", jsonArray);
		return String.valueOf(jsonResponse);
	}
	
	private String convertListNationalityToJson(List<Nationality> nationalitys){
		JsonObject jsonObj;
		JsonArray jsonArray = new JsonArray();
		JsonObject jsonResponse = new JsonObject();
		for(Nationality na: nationalitys){
			jsonObj = new JsonObject();
			jsonObj.addProperty("NationalityID", na.getNationalityID());
			jsonObj.addProperty("NationalityName", na.getNationalityName());
			jsonArray.add(jsonObj);
		}
		jsonResponse.add("NationalityList", jsonArray);
		return String.valueOf(jsonResponse);		
	}
	
	private String convertListLiteracyToJson(List<Literacy> literacys){
		JsonObject jsonResponse = new JsonObject();
		JsonArray jsonArray = new JsonArray();
		JsonObject jsonObj;
		for(Literacy literacy: literacys){
			jsonObj = new JsonObject();
			jsonObj.addProperty("LiteracyID", literacy.getLiteracyID());
			jsonObj.addProperty("LiteracyName", literacy.getLiteracyName());
			jsonArray.add(jsonObj);
		}
		jsonResponse.add("LiteracyList", jsonArray);
		return String.valueOf(jsonResponse);		
	}
	
	private String convertListDepartmentToJson(List<Department> departments){
		JsonObject jsonResponse = new JsonObject();
		JsonArray jsonArray = new JsonArray();
		JsonObject jsonObj;
		for(Department d: departments){
			jsonObj = new JsonObject();
			jsonObj.addProperty("DeptID", d.getDeptID());
			jsonObj.addProperty("DeptName", d.getDeptName());
			jsonArray.add(jsonObj);
		}
		jsonResponse.add("DeptList", jsonArray);
		return String.valueOf(jsonResponse);		
	}
	
	private JsonObject convertListBrandBankToJson(List<BrandBank> brandList){
		JsonObject jsonObj;
		JsonArray jsonArray = new JsonArray();
		JsonObject jsonResponse = new JsonObject();
		for(BrandBank brand: brandList){
			jsonObj = new JsonObject();
			jsonObj.addProperty("BrandBankID", brand.getBrandID());
			jsonObj.addProperty("BrandBankName", brand.getBrandName());
			jsonArray.add(jsonObj);
		}
		jsonResponse.add("BrandBankList", jsonArray);
		return jsonResponse;
	}
}
